#coding=utf-8
import time,uuid


class FakeRedisObj:
    def __init__(self,value,timeout):
        self.value = value
        self.timeout=timeout
        self.buildtime = time.time()

    def valid(self):
        if time.time()-self.buildtime>self.timeout:
            return False
        return True


class FakeRedis:
    _fake_redis={}
    _last_clean = 0
    _clean_interval = 3600
    @staticmethod
    def get_fake_redis(key):
        if key not in FakeRedis._fake_redis:
            FakeRedis._trigger_clean()
            return None
        else:
            obj = FakeRedis._fake_redis[key]
            if obj.valid():
                return obj.value
            else:
                del FakeRedis._fake_redis[key]
                FakeRedis._trigger_clean()
                return None
    @staticmethod
    def set_fake_redis(key,value,timeout):
        FakeRedis._trigger_clean()
        FakeRedis._fake_redis[key]=FakeRedisObj(value,timeout)

    @staticmethod
    def delete_fake_redis(key):
        del FakeRedis._fake_redis[key]
        FakeRedis._trigger_clean()

    @staticmethod
    def _trigger_clean():
        now=time.time()
        if now-FakeRedis._last_clean>FakeRedis._clean_interval:
            FakeRedis._clean_timeout()
            FakeRedis._last_clean=now
    @staticmethod
    def _clean_timeout(max_step=0):
        if max_step==0:
            max_step=len(FakeRedis._fake_redis)
        count=0
        for each_key in FakeRedis._fake_redis.keys():
            obj = FakeRedis._fake_redis[each_key]
            if not obj.valid():
                del FakeRedis._fake_redis[each_key]
            count+=1
            if count>=max_step:
                break



class BaseKeeper:
    _storage = FakeRedis
    _name = None
    _timeout = 3600

    def _get_cache_key(self,key):
        raise NotImplementedError

def generate_token():
    return str(uuid.uuid4())


class SessionKeeper(BaseKeeper):
    _name = 'session'
    _timeout = 3600

    def __init__(self,api_name):
        self._api_name = api_name

    def _get_cache_key(self,key):
        return self._name+'_'+self._api_name + '_'+key

    def get(self,key):
        return self._storage.get_fake_redis(self._get_cache_key(key))

    def build(self,key):
        cache_key = self._get_cache_key(key)
        self._storage.set_fake_redis(cache_key,{},self._timeout)
        return self._storage.get_fake_redis(cache_key)

    def clear(self,key):
        self._storage.delete_fake_redis(self._get_cache_key(key))
